﻿// copyright (c) 2025 author:fio66<fio66@foxmail.com>. All rights reserved.
// date: 2025-09-23 14:31:56
#include "src/audio_device_win32.h"

#include <winerror.h>

#include "logger/logger.hpp"

namespace fio66 {

bool AudioDeviceWin32::Create(const AudioInfo& audio_info) {
  auto ret = ::XAudio2Create(xaudio2_.put(), 0, XAUDIO2_DEFAULT_PROCESSOR);
  if (0 > ret) {
    LOGE << "Create XAudio failed:" << ret;
    return false;
  }
  ret = xaudio2_->CreateMasteringVoice(&xaudio2_master_voice_);
  if(0 > ret) {
    LOGE << "Create XAudio mastering voice failed:" << ret;
    return false;
  }
  WAVEFORMATEX waveFormatEx = {0};
  waveFormatEx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
  waveFormatEx.nChannels = audio_info.channels;  // 从AudioInfo获取声道数
  waveFormatEx.nSamplesPerSec = audio_info.sample_rate;  // 从AudioInfo获取采样率
  waveFormatEx.wBitsPerSample = audio_info.bit_depth;  // 从AudioInfo获取采样位数
  waveFormatEx.nBlockAlign = waveFormatEx.nChannels * waveFormatEx.wBitsPerSample / 8;
  waveFormatEx.nAvgBytesPerSec =
      waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;
  waveFormatEx.cbSize = 0;
  ret = xaudio2_->CreateSourceVoice(&xaudio2_source_voice_, &waveFormatEx, 0, 2.0f, this);
  if (FAILED(ret)) {
    LOGE << "Create XAudio source voice failed:" << ret;
    return false;
  }
  
  return true;
}


void AudioDeviceWin32::Release() {
  Stop();
  if (xaudio2_source_voice_) {
    xaudio2_source_voice_->Stop();
    xaudio2_source_voice_->FlushSourceBuffers();
    xaudio2_source_voice_->DestroyVoice();
    xaudio2_source_voice_ = nullptr;
  }
  
  if (xaudio2_master_voice_) {
    xaudio2_master_voice_->DestroyVoice();
    xaudio2_master_voice_ = nullptr;
  }
  buffers_.clear();
  xaudio2_.detach();
}

void AudioDeviceWin32::Start() {
  if (xaudio2_source_voice_) {
    auto ret =xaudio2_source_voice_->Start(0);
    if(FAILED(ret)) {
      LOGE << "Start audio failed:" << ret;
    }
  }
}

void AudioDeviceWin32::Stop(){
  if (xaudio2_source_voice_) {
    xaudio2_source_voice_->Stop(0);
    xaudio2_source_voice_->FlushSourceBuffers();
  }
}

void AudioDeviceWin32::SetData(std::span<uint8_t> data) {
  if (!xaudio2_source_voice_ || data.empty()) {
    return;
  }
  buffers_.emplace_back(std::vector<uint8_t>(data.begin(), data.end()));
  static bool first = true;
  if(first) {
    first = false;
    Submit();
    Start();
  }
}

bool AudioDeviceWin32::Submit() {
  if (buffer_index_ >= buffers_.size()) {
    return false;
  }
  // 创建音频缓冲区 
  const auto& data = buffers_[buffer_index_];
  XAUDIO2_BUFFER buffer = {0};
  buffer.AudioBytes = static_cast<UINT32>(data.size());
  buffer.pAudioData = data.data();
  buffer.Flags = XAUDIO2_END_OF_STREAM;
  // buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
  // 提交音频数据到源语音
  HRESULT ret = xaudio2_source_voice_->SubmitSourceBuffer(&buffer);

  if (FAILED(ret)) {
    LOGE << "Submit audio buffer failed:" << ret;
    return false;
  }
  buffer_index_++;
  return true;
}
}  // namespace fio66
